/*****************************************************************************
/* Copyright Statement:
*
* This software/firmware and related documentation ("MediaTek Software") are
* protected under relevant copyright laws. The information contained herein
* is confidential and proprietary to MediaTek Inc. and/or its licensors.
* Without the prior written permission of MediaTek inc. and/or its licensors,
* any reproduction, modification, use or disclosure of MediaTek Software,
* and information contained herein, in whole or in part, shall be strictly prohibited.
*/
/* MediaTek Inc. (C) 2015. All rights reserved.
*
*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
*
*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
*
*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
*
*****************************************************************************/

#ifdef BUILD_LK
#include <string.h>
#include <mt_gpio.h>
#include <platform/mt_pmic.h>
#elif defined(BUILD_UBOOT)
#include <asm/arch/mt_gpio.h>
#else
#include <linux/string.h>
#include <mach/mt_gpio.h>
#include <mach/mt_pm_ldo.h>
#endif

#include "lcm_drv.h"
#include <cust_gpio_usage.h>
#if defined(BUILD_LK)
#define LCM_PRINT dprintf
#elif defined(BUILD_UBOOT)
#define LCM_PRINT printf
#else
#define LCM_PRINT printk
#endif
#if defined(BUILD_LK)
#include <boot_mode.h>
//#include <lge_bootmode.h>
#else
#include <mach/board_lge.h>
#endif
#include <upmu_hw.h>

// ---------------------------------------------------------------------------
//  Local Constants
// ---------------------------------------------------------------------------
// pixel
#define FRAME_WIDTH             (1080)
#define FRAME_HEIGHT            (1920)

// physical dimension
#define PHYSICAL_WIDTH        (65)
#define PHYSICAL_HEIGHT         (115)

#define LCM_ID       (0xa5)
#define LCM_DSI_CMD_MODE        0

#define REGFLAG_DELAY 0xAB
#define REGFLAG_END_OF_TABLE 0xAA // END OF REGISTERS MARKER

// ---------------------------------------------------------------------------
//  Local Variables
// ---------------------------------------------------------------------------

static LCM_UTIL_FUNCS lcm_util = {0};

#define SET_RESET_PIN(v)                                    (lcm_util.set_reset_pin((v)))
#define UDELAY(n)                                           (lcm_util.udelay(n))
#define MDELAY(n)                                           (lcm_util.mdelay(n))

// ---------------------------------------------------------------------------
//  Local Functions
// ---------------------------------------------------------------------------

#define dsi_set_cmdq_V3(para_tbl, size, force_update)       lcm_util.dsi_set_cmdq_V3(para_tbl, size, force_update)
#define dsi_set_cmdq_V2(cmd, count, ppara, force_update)            lcm_util.dsi_set_cmdq_V2(cmd, count, ppara, force_update)
#define dsi_set_cmdq(pdata, queue_size, force_update)       lcm_util.dsi_set_cmdq(pdata, queue_size, force_update)
#define wrtie_cmd(cmd)                                      lcm_util.dsi_write_cmd(cmd)
#define write_regs(addr, pdata, byte_nums)                  lcm_util.dsi_write_regs(addr, pdata, byte_nums)
#define read_reg(cmd)                                           lcm_util.dsi_dcs_read_lcm_reg(cmd)
#define read_reg_v2(cmd, buffer, buffer_size)                   lcm_util.dsi_dcs_read_lcm_reg_v2(cmd, buffer, buffer_size)

static unsigned int need_set_lcm_addr = 1;

#ifndef GPIO_LCM_RST
#define GPIO_LCM_RST         (GPIO146 | 0x80000000)
#define GPIO_LCM_RST_M_GPIO   GPIO_MODE_00
#define GPIO_LCM_RST_M_LCM_RST   GPIO_MODE_01
#endif

#ifndef GPIO_TOUCH_RESET
#define GPIO_TOUCH_RESET         (GPIO62 | 0x80000000)
#define GPIO_TOUCH_RESET_M_GPIO   GPIO_MODE_00
#define GPIO_TOUCH_RESET_M_LCM_RST   GPIO_MODE_01
#endif

#ifndef GPIO_EXT_LDO_3V0
#define GPIO_EXT_LDO_3V0         (GPIO64 | 0x80000000) /* GPIO64:CAM1_IOVDD_EN  To Do:  Must be modified for Rev A board */
#define GPIO_EXT_LDO_3V0_M_GPIO   GPIO_MODE_00
#define GPIO_EXT_LDO_3V0_M_LCM_RST   GPIO_MODE_01
#endif


extern kal_uint16 pmic_set_register_value(PMU_FLAGS_LIST_ENUM flagname,kal_uint32 val);
extern void chargepump_DSV_on(void);
extern void chargepump_DSV_off(void);


#define LGE_LPWG_SUPPORT

struct LCM_setting_table {
	unsigned char cmd;
	unsigned char count;
	unsigned char para_list[64];
};

static struct LCM_setting_table lcm_initialization_setting[] = {

	{0x00,  1,  {0x00}},     //[1] Power On #1
	{0xFF,  3,  {0x82, 0x07, 0x01}},     //[1] Power On #2
	{0x00,  1,  {0x80}},     //[1] Power On #1
	{0xFF,  2,  {0x87, 0x07}},     //[1] Power On #2
	{0x00,  1,  {0xB4}},     //[1] Power On #1
	{0xC0,  1,  {0x50}},     //[1] Power On #2
	/*display on*/
	{0x11,  0,  {}},            //[5] sleep out
	{REGFLAG_DELAY, 120, {}},    //MDELAY(120)
	/* exit sleep*/
	{0x29,  0,  {}},            //[3] display on
	{REGFLAG_END_OF_TABLE, 0x00, {}},
};

static LCM_setting_table_V3 lcm_initialization_setting_rotation_V3[] = {
	{0X15, 0X36, 1, {0xC0}}, /* 180 rotation */
	{REGFLAG_END_OF_TABLE, 0x00, 1,{}},
};


static LCM_setting_table_V3 lcm_initialization_setting_V3[] = {

	{0x15, 0x00, 1, {0x00}},        /* CMD2 Enable */
	{0x29, 0xFF, 3, {0x87, 0x07, 0x01}},
	{0x15, 0x00, 1, {0x80}},        /* FocalTech CMD Enable */
	{0x29, 0xFF, 2, {0x87, 0x07}},
	{0x15, 0x00, 1, {0xB4}},        /* X/Y mirror */
	{0x15, 0xC0, 1, {0x50}},


#if 0
	{0x15, 0x00, 1, {0x00}},        /* GVDD/NGVDD */
	{0x29, 0xD8, 2, {0xDA, 0xDA}},
	{0x15, 0x00, 1, {0x00}},        /* Vcom */
	{0x29, 0xD9, 3, {0x03, 0x65, 0x65}},
	{0x15, 0x00, 1, {0x92}},        /* */
	{0x15, 0xC4, 1, {0x01}},
	{0x15, 0x00, 1, {0xA5}},        /* Software Panel Setting*/
	{0x29, 0xB3, 2, {0x17, 0x08}},
#endif
#if 1
	{0x15, 0x00, 1, {0x96}},        /* VGH Clamp(Normal mode)*/
	{0x15, 0xC5, 1, {0x4D}},
	{0x15, 0x00, 1, {0x97}},        /* VGL Clamp(Normal mode) */
	{0x15, 0xC5, 1, {0x3E}},
	{0x15, 0x00, 1, {0xA6}},        /* VGH Clamp(Idle Mode) */
	{0x15, 0xC5, 1, {0x4D}},
	{0x15, 0x00, 1, {0xA7}},        /* VGL Clamp(Idle Mode) */
	{0x15, 0xC5, 1, {0x3E}},
	{0x15, 0x00, 1, {0x98}},        /* VCI1/VCL/VGH/VGL Pump ratio (Normal mode) */
	{0x29, 0xC5, 2, {0x44, 0x44}},
	{0x15, 0x00, 1, {0xA8}},        /* VCI1/VCL/VGH/VGL Pump ratio (Idle mode) */
	{0x29, 0xC5, 2, {0x44, 0x44}},
	{0x15, 0x00, 1, {0x91}},        /* VGHO2 (Normal mode) */
	{0x15, 0xC5, 1, {0x43}},
	{0x15, 0x00, 1, {0x92}},        /* VGLO2 (Normal mode) */
	{0x15, 0xC5, 1, {0x39}},
	{0x15, 0x00, 1, {0xA1}},        /* VGHO2 (Idle mode) */
	{0x15, 0xC5, 1, {0x43}},
	{0x15, 0x00, 1, {0xA2}},        /* VGLO2 (Idle mode) */
	{0x15, 0xC5, 1, {0x39}},
	{0x15, 0x00, 1, {0x00}},        /* GVDD/NGVDD */
	{0x29, 0xD8, 2, {0xC8, 0xC8}},

	/* Panel timming */
	{0x15, 0x00, 1, {0x80}},
	{0x29, 0xC2, 12, {0x87, 0x00, 0x00, 0x03, 0x86,   0x00, 0x00, 0x03, 0x85, 0x00,   0x00, 0x03}},
	{0x15, 0x00, 1, {0x90}},
	{0x29, 0xC2, 12, {0x84, 0x00, 0x00, 0x03, 0x83,   0x01, 0x00, 0x03, 0x82, 0x02,   0x00, 0x03}},
	{0x15, 0x00, 1, {0xA0}},
	{0x29, 0xC2, 12, {0x81, 0x03, 0x00, 0x03, 0x00,   0x04, 0x00, 0x03, 0x00, 0x00,   0x00, 0x00}},
	{0x15, 0x00, 1, {0xB0}},
	{0x29, 0xC2, 12, {0x00, 0x00, 0x00, 0x00, 0x00,   0x00, 0x00, 0x00, 0x00, 0x00,   0x00, 0x00}},
	{0x15, 0x00, 1, {0xC0}},
	{0x29, 0xC2, 12, {0x00, 0x00, 0x00, 0x00, 0x00,   0x00, 0x00, 0x00, 0x00, 0x00,   0x00, 0x00}},
	{0x15, 0x00, 1, {0xD0}},
	{0x29, 0xC2, 11, {0x00, 0x00, 0x00, 0x00, 0x07,   0x17, 0x97, 0x00, 0x17, 0x97,   0x00}},
	{0x15, 0x00, 1, {0x80}},
	{0x29, 0xC3, 14, {0x8B, 0x00, 0x00, 0x8A, 0x00,   0x00, 0x89, 0x00, 0x00, 0x88,   0x00, 0x00, 0x33, 0x33}},
	{0x15, 0x00, 1, {0xA0}},
	{0x29, 0xC3, 15, {0x00, 0x02, 0x01, 0x00, 0x02,   0x01, 0x00, 0x02, 0x0F, 0x0F,   0x02, 0x0F, 0x0F, 0xC1, 0x00}},
	{0x15, 0x00, 1, {0xB0}},
	{0x29, 0xC3, 15, {0x00, 0x00, 0x00, 0x00, 0x00,   0x00, 0x00, 0x00, 0x02, 0x00,   0x00, 0x02, 0x02, 0x01, 0x01}},
	{0x15, 0x00, 1, {0x80}},
	{0x29, 0xCB, 15, {0x40, 0x40, 0x40, 0x40, 0x40,   0x40, 0x40, 0x40, 0x40, 0x40,   0x40, 0x40, 0x40, 0x40, 0x40}},
	{0x15, 0x00, 1, {0x90}},
	{0x29, 0xCB, 15, {0x00, 0x00, 0x00, 0x00, 0x00,   0x40, 0x40, 0x40, 0x40, 0x40,   0x40, 0x40, 0x40, 0x40, 0x40}},
	{0x15, 0x00, 1, {0xA0}},
	{0x29, 0xCB, 10, {0x40, 0x40, 0x40, 0x40, 0x40,   0x00, 0x00, 0x00, 0x00, 0x00}},
	{0x15, 0x00, 1, {0xB0}},
	{0x29, 0xCB, 15, {0x01, 0x05, 0x05, 0x01, 0x01,   0xC5, 0xC5, 0xC5, 0xC5, 0xC5,   0xC5, 0xC5, 0xC5, 0xC5, 0xC5}},
	{0x15, 0x00, 1, {0xC0}},
	{0x29, 0xCB, 15, {0x01, 0x01, 0x01, 0x01, 0x01,   0x01, 0x05, 0x05, 0x01, 0x01,   0x01, 0x01, 0x01, 0x01, 0x01}},
	{0x15, 0x00, 1, {0xD0}},
	{0x29, 0xCB, 11, {0x01, 0x01, 0x01, 0x01, 0x01,   0x01, 0x01, 0x01, 0x01, 0x01,   0x00}},
	{0x15, 0x00, 1, {0x80}},
	{0x29, 0xCC, 15, {0x32, 0x02, 0x01, 0x23, 0x24,   0x09, 0x09, 0x07, 0x07, 0x0D,   0x0D, 0x0B, 0x0B, 0x17, 0x19}},
	{0x15, 0x00, 1, {0x90}},
	{0x29, 0xCC, 15, {0x01, 0x01, 0x3A, 0x3A, 0x3A,   0x32, 0x02, 0x01, 0x23, 0x24,   0x0A, 0x0A, 0x08, 0x08, 0x0E}},
	{0x15, 0x00, 1, {0xA0}},
	{0x29, 0xCC, 10, {0x0E, 0x0C, 0x0C, 0x18, 0x1A,   0x01, 0x01, 0x3A, 0x3A, 0x3A}},
	{0x15, 0x00, 1, {0xB0}},
	{0x29, 0xCC, 15, {0x32, 0x01, 0x02, 0x23, 0x24,   0x0C, 0x0C, 0x0E, 0x0E, 0x08,   0x08, 0x0A, 0x0A, 0x1A, 0x18}},
	{0x15, 0x00, 1, {0xC0}},
	{0x29, 0xCC, 15, {0x01, 0x01, 0x3A, 0x3A, 0x3A,   0x32, 0x01, 0x02, 0x23, 0x24,   0x0B, 0x0B, 0x0D, 0x0D, 0x07}},
	{0x15, 0x00, 1, {0xD0}},
	{0x29, 0xCC, 10, {0x07, 0x09, 0x09, 0x19, 0x17,   0x01, 0x01, 0x3A, 0x3A, 0x3A}},
	{0x15, 0x00, 1, {0xE0}},
	{0x29, 0xCC, 15, {0x00, 0x00, 0x00, 0x00, 0x00,   0x00, 0x00, 0x00, 0x00, 0x00,   0x05, 0x05, 0x05, 0x05, 0x05}},
	{0x15, 0x00, 1, {0xF0}},
	{0x29, 0xCC, 8, {0x00, 0x00, 0x00, 0x00, 0x00,   0x00, 0x00, 0x00}},

	/* Positive Gamma */
	{0x15, 0x00, 1, {0x00}},
	{0x29, 0xE1, 15, {0x00, 0x1A, 0x37, 0x4C, 0x58,   0x63, 0x75, 0x82, 0x82, 0x8D,   0x8D, 0x9E, 0x69, 0x5A, 0x5D}},
	{0x15, 0x00, 1, {0x10}},
	{0x29, 0xE1, 9, {0x53, 0x4C, 0x43, 0x36, 0x2D,   0x25, 0x15, 0x01, 0x00}},

	/*Positive Gamma */
	{0x15, 0x00, 1, {0x00}},
	{0x29, 0xE2, 15, {0x00, 0x1A, 0x37, 0x4C, 0x58,   0x63, 0x75, 0x82, 0x83, 0x8E,   0x8D, 0x9E, 0x69, 0x59, 0x5D}},
	{0x15, 0x00, 1, {0x10}},
	{0x29, 0xE2, 9, {0x52, 0x4C, 0x43, 0x35, 0x2D,   0x25, 0x15, 0x01, 0x00}},

	/* */
	{0x15, 0x00, 1, {0x00}},    /* RAM Compressing Setting */
	{0x15, 0x1C, 1, {0x03}},
	{0x15, 0x00, 1, {0x90}},
	{0x15, 0xF4, 1, {0x08}},
	{0x15, 0x00, 1, {0x8D}},
	{0x29, 0xA4, 2, {0x01, 0x60}},
	{0x15, 0x00, 1, {0x90}},
	{0x29, 0xF5, 4, {0x4A, 0x00, 0x4A, 0x00}},
	{0x15, 0x00, 1, {0x91}},
	{0x29, 0xF4, 3, {0x03, 0x33, 0x33}},
	{0x15, 0x00, 1, {0x92}},
	{0x15, 0xC4, 1, {0x01}},
	{0x15, 0x00, 1, {0xA5}},    /* Software Panel Setting */
	{0x29, 0xB3, 2, {0x17, 0x08}},
	{0x15, 0x00, 1, {0x80}},
	{0x15, 0xC4, 1, {0x00}},
	{0x15, 0x00, 1, {0x81}},    /* Vcom Path */
	{0x15, 0xA5, 1, {0x03}},
	{0x15, 0x00, 1, {0xA4}},
	{0x29, 0xCF, 4, {0x00, 0x07, 0x20, 0x70}},
	{0x15, 0x00, 1, {0x94}},
	{0x29, 0xCF, 4, {0x00, 0x00, 0x80, 0x90}},
	{0x15, 0x00, 1, {0x98}},
	{0x29, 0xCF, 4, {0x04, 0x04, 0x86, 0x96}},
	{0x15, 0x00, 1, {0xA0}},
	{0x29, 0xCF, 4, {0x07, 0x07, 0x10, 0x20}},
	{0x15, 0x00, 1, {0x82}},            /* VGHO & VGLO Delta Set */
	{0x15, 0xC5, 1, {0x0F}},
	{0x15, 0x00, 1, {0xD1}},
	{0x29, 0xCF, 4, {0x02, 0x04, 0x01, 0xFF}},
	{0x15, 0x00, 1, {0xD7}},
	{0x29, 0xCF, 4, {0x02, 0x04, 0x00, 0x06}},
	{0x15, 0x00, 1, {0xB0}},
	{0x29, 0xC5, 3, {0x20, 0x20, 0x01}},
	{0x15, 0x00, 1, {0x83}},            /* TON VFPLO */
	{0x15, 0xC0, 1, {0xEA}},
	{0x15, 0x00, 1, {0xA2}},
	{0x29, 0xF5, 2, {0x80, 0xC0}},
	{0x15, 0x00, 1, {0x85}},            /* VGHO1 & VGLO1 off Set */
	{0x15, 0xC5, 1, {0x01}},
	{0x15, 0x00, 1, {0x99}},            /* Glance Mode VBP/VFP Set */
	{0x29, 0xC0, 4, {0x07, 0x80, 0x07, 0x80}},

#endif

#if 0
	{0x15, 0x00, 1, {0x98}},        /* VCI1/VCL Pump ratio Normal mode */
	{0x29, 0xC5, 2, {0x22, 0x22}},
	{0x15, 0x00, 1, {0xA8}},        /* VCI1/VCL Pump ratio idle mode */
	{0x29, 0xC5, 2, {0x22, 0x22}},
	{0x15, 0x00, 1, {0xD2}},        /* Thermo Vol INC DM */
	{0x15, 0xC5, 1, {0x00}},
	{0x15, 0x00, 1, {0x97}},        /* VGL Clamp */
	{0x15, 0xC5, 1, {0x39}},
	{0x15, 0x00, 1, {0x92}},        /* VGLO */
	{0x15, 0xC5, 1, {0x39}},
	{0x15, 0x00, 1, {0x95}},        /* Pumping ratio */
	{0x15, 0xC5, 1, {0xA1}},
	{0x15, 0x00, 1, {0x96}},        /* VGH Clamp */
	{0x15, 0xC5, 1, {0x6B}},
	{0x15, 0x00, 1, {0x91}},        /* VGHO */
	{0x15, 0xC5, 1, {0x43}},
	{0x15, 0x00, 1, {0x00}},        /* GVDD/NGVDD */
	{0x29, 0xD8, 2, {0xDA, 0xDA}},
	{0x15, 0x00, 1, {0x81}},        /* Vcom power */
	{0x15, 0xA5, 1, {0x0B}},
	{0x15, 0x00, 1, {0x00}},        /* Vcom */
	{0x29, 0xD9, 3, {0x03, 0x65, 0x65}},
	{0x15, 0x00, 1, {0xD4}},        /* Thermal setting */
	{0x15, 0xC5, 1, {0x42}},
	{0x15, 0x00, 1, {0xD5}},
	{0x15, 0xC5, 1, {0x44}},

	/* Panel timming */
	{0x15, 0x00, 1, {0x80}},
	{0x29, 0xC2, 12, {0x87, 0x00, 0x00, 0x03, 0x86, 0x00, 0x00, 0x03, 0x85, 0x00, 0x00, 0x03}},
	{0x15, 0x00, 1, {0x90}},
	{0x29, 0xC2, 12, {0x84, 0x00, 0x00, 0x03, 0x83, 0x01, 0x00, 0x03, 0x82, 0x02, 0x00, 0x03}},
	{0x15, 0x00, 1, {0xA0}},
	{0x29, 0xC2, 12, {0x81, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00}},
	{0x15, 0x00, 1, {0xB0}},
	{0x29, 0xC2, 12, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
	{0x15, 0x00, 1, {0xC0}},
	{0x29, 0xC2, 12, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
	{0x15, 0x00, 1, {0xD0}},
	{0x29, 0xC2, 11, {0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x93, 0x00, 0x00, 0x93, 0x00}},
	{0x15, 0x00, 1, {0x80}},
	{0x29, 0xC3, 14, {0x8B, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x89, 0x00, 0x00, 0x88, 0x00, 0x00, 0x33, 0x33}},
	{0x15, 0x00, 1, {0xA0}},
	{0x29, 0xC3, 15, {0x00, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x02, 0x0F, 0x0F, 0x02, 0x0F, 0x0F, 0xC0, 0x00}},
	{0x15, 0x00, 1, {0xB0}},
	{0x29, 0xC3, 15, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x06, 0x02, 0x02, 0x01, 0x01}},
	{0x15, 0x00, 1, {0x80}},
	{0x29, 0xCB, 15, {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}},
	{0x15, 0x00, 1, {0x90}},
	{0x29, 0xCB, 15, {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}},
	{0x15, 0x00, 1, {0xA0}},
	{0x29, 0xCB, 10, {0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00}},
	{0x15, 0x00, 1, {0xB0}},
	{0x29, 0xCB, 15, {0x01, 0x05, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}},
	{0x15, 0x00, 1, {0xC0}},
	{0x29, 0xCB, 15, {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}},
	{0x15, 0x00, 1, {0xD0}},
	{0x29, 0xCB, 11, {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00}},
	{0x15, 0x00, 1, {0x80}},
	{0x29, 0xCC, 15, {0x32, 0x02, 0x01, 0x23, 0x24, 0x09, 0x09, 0x07, 0x07, 0x0D, 0x0D, 0x0B, 0x0B, 0x17, 0x19}},
	{0x15, 0x00, 1, {0x90}},
	{0x29, 0xCC, 15, {0x01, 0x01, 0x3A, 0x3A, 0x3A, 0x32, 0x02, 0x01, 0x23, 0x24, 0x0A, 0x0A, 0x08, 0x08, 0x0E}},
	{0x15, 0x00, 1, {0xA0}},
	{0x29, 0xCC, 10, {0x0E, 0x0C, 0x0C, 0x18, 0x1A, 0x01, 0x01, 0x3A, 0x3A, 0x3A}},
	{0x15, 0x00, 1, {0xB0}},
	{0x29, 0xCC, 15, {0x32, 0x01, 0x02, 0x23, 0x24, 0x0C, 0x0C, 0x0E, 0x0E, 0x08, 0x08, 0x0A, 0x0A, 0x1A, 0x18}},
	{0x15, 0x00, 1, {0xC0}},
	{0x29, 0xCC, 15, {0x01, 0x01, 0x3A, 0x3A, 0x3A, 0x32, 0x01, 0x02, 0x23, 0x24, 0x0B, 0x0B, 0x0D, 0x0D, 0x07}},
	{0x15, 0x00, 1, {0xD0}},
	{0x29, 0xCC, 10, {0x07, 0x09, 0x09, 0x19, 0x17, 0x01, 0x01, 0x3A, 0x3A, 0x3A}},
	{0x15, 0x00, 1, {0xE0}},
	{0x29, 0xCC, 15, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
	{0x15, 0x00, 1, {0xF0}},
	{0x29, 0xCC, 8, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
	/* Positive Gamma */
	{0x15, 0x00, 1, {0x00}},
	{0x15, 0xE1, 1, {0x06}},
	{0x15, 0x00, 1, {0x01}},
	{0x15, 0xE1, 1, {0x2A}},
	{0x15, 0x00, 1, {0x02}},
	{0x15, 0xE1, 1, {0x48}},
	{0x15, 0x00, 1, {0x03}},
	{0x15, 0xE1, 1, {0x5C}},
	{0x15, 0x00, 1, {0x04}},
	{0x15, 0xE1, 1, {0x68}},
	{0x15, 0x00, 1, {0x05}},
	{0x15, 0xE1, 1, {0x74}},
	{0x15, 0x00, 1, {0x06}},
	{0x15, 0xE1, 1, {0x85}},
	{0x15, 0x00, 1, {0x07}},
	{0x15, 0xE1, 1, {0x8F}},
	{0x15, 0x00, 1, {0x08}},
	{0x15, 0xE1, 1, {0x8F}},
	{0x15, 0x00, 1, {0x09}},
	{0x15, 0xE1, 1, {0x9A}},
	{0x15, 0x00, 1, {0x0A}},
	{0x15, 0xE1, 1, {0x97}},
	{0x15, 0x00, 1, {0x0B}},
	{0x15, 0xE1, 1, {0xA7}},
	{0x15, 0x00, 1, {0x0C}},
	{0x15, 0xE1, 1, {0x61}},
	{0x15, 0x00, 1, {0x0D}},
	{0x15, 0xE1, 1, {0x53}},
	{0x15, 0x00, 1, {0x0E}},
	{0x15, 0xE1, 1, {0x58}},
	{0x15, 0x00, 1, {0x10}},
	{0x15, 0xE1, 1, {0x4F}},
	{0x15, 0x00, 1, {0x11}},
	{0x15, 0xE1, 1, {0x49}},
	{0x15, 0x00, 1, {0x12}},
	{0x15, 0xE1, 1, {0x3F}},
	{0x15, 0x00, 1, {0x13}},
	{0x15, 0xE1, 1, {0x33}},
	{0x15, 0x00, 1, {0x14}},
	{0x15, 0xE1, 1, {0x2A}},
	{0x15, 0x00, 1, {0x15}},
	{0x15, 0xE1, 1, {0x23}},
	{0x15, 0x00, 1, {0x16}},
	{0x15, 0xE1, 1, {0x15}},
	{0x15, 0x00, 1, {0x17}},
	{0x15, 0xE1, 1, {0x01}},
	{0x15, 0x00, 1, {0x18}},
	{0x15, 0xE1, 1, {0x00}},

	/*Positive Gamma */
	{0x15, 0x00, 1, {0x00}},
	{0x15, 0xE2, 1, {0x06}},
	{0x15, 0x00, 1, {0x01}},
	{0x15, 0xE2, 1, {0x2A}},
	{0x15, 0x00, 1, {0x02}},
	{0x15, 0xE2, 1, {0x47}},
	{0x15, 0x00, 1, {0x03}},
	{0x15, 0xE2, 1, {0x5C}},
	{0x15, 0x00, 1, {0x04}},
	{0x15, 0xE2, 1, {0x68}},
	{0x15, 0x00, 1, {0x05}},
	{0x15, 0xE2, 1, {0x74}},
	{0x15, 0x00, 1, {0x06}},
	{0x15, 0xE2, 1, {0x83}},
	{0x15, 0x00, 1, {0x07}},
	{0x15, 0xE2, 1, {0x8F}},
	{0x15, 0x00, 1, {0x08}},
	{0x15, 0xE2, 1, {0x8F}},
	{0x15, 0x00, 1, {0x09}},
	{0x15, 0xE2, 1, {0x99}},
	{0x15, 0x00, 1, {0x0A}},
	{0x15, 0xE2, 1, {0x97}},
	{0x15, 0x00, 1, {0x0B}},
	{0x15, 0xE2, 1, {0xA6}},
	{0x15, 0x00, 1, {0x0C}},
	{0x15, 0xE2, 1, {0x62}},
	{0x15, 0x00, 1, {0x0D}},
	{0x15, 0xE2, 1, {0x53}},
	{0x15, 0x00, 1, {0x0E}},
	{0x15, 0xE2, 1, {0x58}},
	{0x15, 0x00, 1, {0x10}},
	{0x15, 0xE2, 1, {0x4F}},
	{0x15, 0x00, 1, {0x11}},
	{0x15, 0xE2, 1, {0x4A}},
	{0x15, 0x00, 1, {0x12}},
	{0x15, 0xE2, 1, {0x3F}},
	{0x15, 0x00, 1, {0x13}},
	{0x15, 0xE2, 1, {0x33}},
	{0x15, 0x00, 1, {0x14}},
	{0x15, 0xE2, 1, {0x2B}},
	{0x15, 0x00, 1, {0x15}},
	{0x15, 0xE2, 1, {0x23}},
	{0x15, 0x00, 1, {0x16}},
	{0x15, 0xE2, 1, {0x15}},
	{0x15, 0x00, 1, {0x17}},
	{0x15, 0xE2, 1, {0x01}},
	{0x15, 0x00, 1, {0x18}},
	{0x15, 0xE2, 1, {0x00}},

	/* */
	{0x15, 0x00, 1, {0xD9}},
	{0x29, 0x00, 3, {0x03, 0x90, 0x90}},
	{0x15, 0x00, 1, {0x00}},    /* RAM Compressing Setting */
	{0x15, 0x1C, 1, {0x03}},
	{0x15, 0x00, 1, {0x81}},
	{0x15, 0xA5, 1, {0x0A}},
	{0x15, 0x00, 1, {0xC1}},
	{0x15, 0xC5, 1, {0x16}},    /* Power Control */
	{0x15, 0x00, 1, {0x85}},
	{0x15, 0xF4, 1, {0x29}},
	{0x15, 0x00, 1, {0x90}},
	{0x15, 0xF4, 1, {0x08}},
	{0x15, 0x00, 1, {0xB9}},    /* GIP setting */
	{0x15, 0xC3, 1, {0x02}},
	{0x15, 0x00, 1, {0x9A}},
	{0x29, 0xCE, 4, {0x00, 0x00, 0x00, 0x00}},
	{0x15, 0x00, 1, {0x8D}},
	{0x29, 0xA4, 2, {0x01, 0x59}},
	{0x15, 0x00, 1, {0x90}},
	{0x29, 0xF5, 4, {0x4A, 0x4A, 0x4A, 0x4A}},
	{0x15, 0x00, 1, {0x91}},
	{0x29, 0xF4, 3, {0x03, 0x33, 0x33}},
	{0x15, 0x00, 1, {0x92}},
	{0x15, 0xC4, 1, {0x01}},
	{0x15, 0x00, 1, {0xA5}},    /* Software Panel Setting */
	{0x29, 0xB3, 2, {0x17, 0x08}},

#endif

	{0X05, 0X11, 1, {0x00}},
	{REGFLAG_ESCAPE_ID, REGFLAG_DELAY_MS_V3, 120,{}},
	{0X05, 0X29, 1, {0x00}},
	{REGFLAG_ESCAPE_ID, REGFLAG_DELAY_MS_V3, 5,{}},
	{REGFLAG_END_OF_TABLE, 0x00, 1,{}},
};


static LCM_setting_table_V3 lcm_initialization_setting_V3_Disp_On[] = {
	{0x05, 0x11,    1, {0x00}},
	{REGFLAG_ESCAPE_ID, REGFLAG_DELAY_MS_V3, 120,{}},
	{0x05, 0x29,    1, {0x00}},
	{REGFLAG_END_OF_TABLE, 0x00, 1,{}},
};

static LCM_setting_table_V3 lcm_initialization_for_sleep_in_pre[] = {
	{0x05, 0x28,    1, {0x00}},
	{REGFLAG_ESCAPE_ID, REGFLAG_DELAY_MS_V3, 60,{}},
	{0x05, 0x10, 1, {0x00}},
	{REGFLAG_END_OF_TABLE, 0x00, 1,{}},
};

static struct LCM_setting_table __attribute__ ((unused)) lcm_backlight_level_setting[] = {
	{0x51, 1, {0xFF}},
	{REGFLAG_END_OF_TABLE, 0x00, {}}
};

static void push_table(struct LCM_setting_table *table, unsigned int count, unsigned char force_update)
{
	unsigned int i;

	for (i = 0; i < count; i++) {
		unsigned cmd;

		cmd = table[i].cmd;

		switch (cmd) {
			case REGFLAG_DELAY:
				MDELAY(table[i].count);
				break;

			case REGFLAG_END_OF_TABLE:
				break;

			default:
				dsi_set_cmdq_V2(cmd, table[i].count, table[i].para_list, force_update);
		}
	}
	dprintf(INFO,"[LCD] push_table \n");
}
// ---------------------------------------------------------------------------
//  LCM Driver Implementations
// ---------------------------------------------------------------------------
static void lcm_set_util_funcs(const LCM_UTIL_FUNCS *util)
{
	memcpy((void*)&lcm_util, (void*)util, sizeof(LCM_UTIL_FUNCS));
}

static void lcm_get_params(LCM_PARAMS * params)
{
	memset(params, 0, sizeof(LCM_PARAMS));

	params->type   = LCM_TYPE_DSI;

	params->width  = FRAME_WIDTH;
	params->height = FRAME_HEIGHT;

	// physical size
	params->physical_width = PHYSICAL_WIDTH;
	params->physical_height = PHYSICAL_HEIGHT;

	params->dsi.mode   = SYNC_EVENT_VDO_MODE; //BURST_VDO_MODE;//SYNC_PULSE_VDO_MODE;
	// enable tearing-free
	params->dbi.te_mode                 = LCM_DBI_TE_MODE_DISABLED;
	params->dbi.te_edge_polarity        = LCM_POLARITY_RISING;

	// DSI
	/* Command mode setting */
	params->dsi.LANE_NUM                    = LCM_FOUR_LANE;
	//The following defined the fomat for data coming from LCD engine.
	params->dsi.data_format.color_order     = LCM_COLOR_ORDER_RGB;
	params->dsi.data_format.trans_seq       = LCM_DSI_TRANS_SEQ_MSB_FIRST;
	params->dsi.data_format.padding         = LCM_DSI_PADDING_ON_LSB;
	params->dsi.data_format.format          = LCM_DSI_FORMAT_RGB888;

	// Highly depends on LCD driver capability.
	params->dsi.packet_size=256;
	//params->dsi.intermediat_buffer_num = 0;

	params->dsi.PS=LCM_PACKED_PS_24BIT_RGB888;
	//params->dsi.cont_clock = TRUE;

	params->dsi.vertical_sync_active    = 4; //1; //20150824 , 1->2
	params->dsi.vertical_backporch      = 12; //3;
	params->dsi.vertical_frontporch     = 234; //7;
	params->dsi.vertical_active_line    = FRAME_HEIGHT;

	params->dsi.horizontal_sync_active  = 4; //12;
	params->dsi.horizontal_backporch    = 32; //36; //45;
	params->dsi.horizontal_frontporch   = 32; //96; //50; //96;
	params->dsi.horizontal_active_pixel     = FRAME_WIDTH;

	//params->dsi.HS_TRAIL = 10;
	//params->dsi.HS_ZERO= 20;
	//params->dsi.LPX= 20;
	//params->dsi.HS_PRPR= 8;

	params->dsi.PLL_CLOCK = 480; //490(60.30); //464; //426(55fps); //338; //312; // 234;

}

static void init_lcm_registers(void)
{
	unsigned int data_array[32];

	//push_table(lcm_initialization_setting, sizeof(lcm_initialization_setting) / sizeof(struct LCM_setting_table), 1);
	dsi_set_cmdq_V3(lcm_initialization_setting_V3, sizeof(lcm_initialization_setting_V3) / sizeof(LCM_setting_table_V3), 1);
	dprintf(INFO,"[LCD] init_lcm_registers focal \n");


}

static void init_lcm_registers_sleep(void)
{
	unsigned int data_array[1];
	dsi_set_cmdq_V3(lcm_initialization_for_sleep_in_pre, sizeof(lcm_initialization_for_sleep_in_pre) / sizeof(LCM_setting_table_V3), 1);
	MDELAY(60);
	dprintf(INFO,"[LCD] init_lcm_registers_sleep \n");
}

static void init_lcm_registers_sleep_out(void)
{
	unsigned int data_array[1];

	data_array[0] = 0x00110500;
	dsi_set_cmdq(data_array, 1, 1);
	MDELAY(150);
	data_array[0] = 0x00290500;
	dsi_set_cmdq(data_array, 1, 1);
	MDELAY(50);
	dprintf(INFO,"[LCD] init_lcm_registers_sleep \n");
}

/* VCAMD 1.8v LDO enable */
static void ldo_1v8io_on(void)
{
	mt6328_set_register_value(PMIC_RG_VRF18_1_VOSEL, 3);
	mt6328_set_register_value(PMIC_RG_VRF18_1_EN, 1);
}

/* VCAMD 1.8v LDO disable */
static void ldo_1v8io_off(void)
{
	mt6328_set_register_value(PMIC_RG_VRF18_1_EN, 0);
}

/* VGP2 3.0v LDO enable */
static void ldo_3v0_on(void)
{
	mt6328_set_register_value(PMIC_RG_VGP1_VOSEL, 6);
	mt6328_set_register_value(PMIC_RG_VGP1_EN, 1);
}

/* VGP2 3.0v LDO disable */
static void ldo_3v0_off(void)
{
	mt6328_set_register_value(PMIC_RG_VGP1_EN, 0);
}

/* DSV power +5V,-5v */
static void ldo_p5m5_dsv_5v5_on(void)
{
#if defined(BUILD_LK)
	chargepump_DSV_on();
#else
	rt4832_dsv_ctrl(1);
#endif

}

static void ldo_p5m5_dsv_5v5_off(void)
{
#if defined(BUILD_LK)
	chargepump_DSV_off();
#else
	rt4832_dsv_ctrl(0);
#endif
}

static void reset_lcd_module(unsigned char reset)
{
	mt_set_gpio_mode(GPIO_LCM_RST, GPIO_LCM_RST_M_GPIO);
	//mt_set_gpio_pull_enable(GPIO_LCM_RST, GPIO_PULL_ENABLE);
	mt_set_gpio_dir(GPIO_LCM_RST, GPIO_DIR_OUT);

	if (reset) {
		mt_set_gpio_out(GPIO_LCM_RST, GPIO_OUT_ONE);
		dprintf(INFO,"[LCD] Reset High \n");
	} else {
		mt_set_gpio_out(GPIO_LCM_RST, GPIO_OUT_ZERO);
		dprintf(INFO,"[LCD] Reset Low \n");
	}
}

static void touch_reset_pin (int mode)
{
	mt_set_gpio_mode(GPIO_TOUCH_RESET, GPIO_TOUCH_RESET_M_GPIO);
	mt_set_gpio_dir(GPIO_TOUCH_RESET, GPIO_DIR_OUT);

	if (mode == 1) {
		mt_set_gpio_out(GPIO_TOUCH_RESET, GPIO_OUT_ONE);
	} else if (mode == 0) {
		mt_set_gpio_out(GPIO_TOUCH_RESET, GPIO_OUT_ZERO);
	}
}

static void set_ext_ldo_3v0(int on)
{
	mt_set_gpio_mode(GPIO_EXT_LDO_3V0, GPIO_EXT_LDO_3V0_M_GPIO);
	mt_set_gpio_dir(GPIO_EXT_LDO_3V0, GPIO_DIR_OUT);

	if (on == 1) {
		mt_set_gpio_out(GPIO_EXT_LDO_3V0, GPIO_OUT_ONE);
	} else {
		mt_set_gpio_out(GPIO_EXT_LDO_3V0, GPIO_OUT_ZERO);
	}
}

static void lcm_init_power(void)
{
	reset_lcd_module(0);
	touch_reset_pin(0);

	MDELAY(2);
	ldo_p5m5_dsv_5v5_on();
	MDELAY(10);
	touch_reset_pin(1);

	reset_lcd_module(1);
	MDELAY(2);
	reset_lcd_module(0);
	MDELAY(2);
	reset_lcd_module(1);
	MDELAY(20);
}
static void lcm_init(void)
{
	init_lcm_registers();

	need_set_lcm_addr = 1;
	dprintf(INFO,"[LCD] lcm_init test\n");
}

static void lcm_suspend(void)
{
	init_lcm_registers_sleep();
	dprintf(INFO,"[LCD] lcm_suspend \n");
}

static void lcm_resume(void)
{
#if 0
	touch_reset_pin(0);
	MDELAY(10);
	reset_lcd_module(0);
	MDELAY(10);
	ldo_p5m5_dsv_5v5_off();
	MDELAY(10);
	ldo_1v8io_off();
	MDELAY(1);
	ldo_3v0_off();
	MDELAY(20);
	lcm_init();
#else
	init_lcm_registers_sleep_out();
#endif
	need_set_lcm_addr = 1;
	dprintf(INFO,"[LCD] lcm_resume \n");
}

static void lcm_esd_recover(void)
{
	lcm_suspend();
	lcm_resume();

	dprintf(INFO,"[LCD] lcm_esd_recover \n");
}



static unsigned int lcm_compare_id(void)
{
	dprintf(INFO, "lcm_compare_id default focaltech DIC\n");
	return 1;
}
// ---------------------------------------------------------------------------
//  Get LCM Driver Hooks
// ---------------------------------------------------------------------------
LCM_DRIVER ft8707_fhd_dsi_vdo_lgd_drv = {
	.name = "ft8707_fhd_dsi_vdo_lgd",
	.set_util_funcs = lcm_set_util_funcs,
	.get_params = lcm_get_params,
	.init_power = lcm_init_power,
	.init = lcm_init,
	.suspend = lcm_suspend,
	.resume = lcm_resume,
	.compare_id = lcm_compare_id,
#if (!defined(BUILD_UBOOT) && !defined(BUILD_LK))
//	.esd_recover = lcm_esd_recover,
#endif
};
